<template>
  <div class="PageForm">
    <el-form
      ref="ruleFormRef"
      :model="formData"
      :rules="rules"
      :label-position="labelPosition"
      :label-width="labelWidth"
      @submit.prevent.stop
      @submit.native.prevent.stop
    >
      <el-row v-for="(item, index) in list" :key="index" :gutter="20">
        <el-col
          v-for="(target, key) in item.list"
          :key="key"
          :span="target.span"
          :offset="target.offset"
        >
          <el-form-item
            v-if="!target.hidden"
            style="margin-top: 10px; margin-bottom: 10px"
            :prop="target.prop"
            :label="target.label"
          >
            <template v-if="target.component === 'input'">
              <el-input
                clearable
                :value="formData[target.prop]"
                @input="handleInput(target.prop, $event)"
                :style="{
                  width: target && target.width ? target.width : '100%',
                }"
                :disabled="target.disabled"
                :placeholder="
                  target.componentProps && target.componentProps.placeholder
                "
              >
                <template
                  v-if="target.componentProps && target.componentProps.prepend"
                  slot="prepend"
                >
                  <div style="text-align: right; width: 70px">
                    {{ target.componentProps.prepend }}
                  </div>
                </template>

                <template
                  v-if="target.componentProps && target.componentProps.append"
                  slot="append"
                >
                  <slot :name="target.componentProps.append" />
                </template>
              </el-input>
            </template>

            <template v-else-if="target.component === 'textarea'">
              <el-input
                :value="formData[target.prop]"
                @input="handleInput(target.prop, $event)"
                :autosize="{ minRows: 5, maxRows: 6 }"
                type="textarea"
                v-bind="target.componentProps"
              />
            </template>

            <template v-else-if="target.component === 'number'">
              <el-input-number
                :value="formData[target.prop]"
                @input="handleInput(target.prop, $event)"
                v-bind="target.componentProps"
                :min="0"
                :disabled="target.disabled"
                :max="target.max"
                controls-position="right"
                size="large"
                @change="target.onInput && target.onInput($event)"
              />
            </template>

            <template v-else-if="target.component === 'button'">
              <el-button v-bind="target.componentProps" />
            </template>

            <template v-else-if="target.component === 'switch'">
              <el-switch
                :value="formData[target.prop]"
                @input="handleInput(target.prop, $event)"
                v-bind="target.componentProps"
                :active-value="target.active"
                :inactive-value="target.inactive"
                @change="
                  () =>
                    target &&
                    target.switchProps &&
                    target.switchProps.onChange &&
                    target.switchProps.onChange(formData[target.prop])
                "
              />
            </template>

            <template v-else-if="target.component === 'treeSelect'">
              <el-tree-select
                :value="formData[target.prop]"
                @input="handleInput(target.prop, $event)"
                :data="target.treeSelectList"
                check-strictly
                :render-after-expand="false"
                :multiple="target.multiple"
                :show-checkbox="target.checkbox"
              />
            </template>

            <template v-else-if="target.component === 'radioGroup'">
              <el-radio-group
                :value="formData[target.prop]"
                @input="handleInput(target.prop, $event)"
                v-bind="target.componentProps"
                :disabled="target.disabled"
              >
                <el-radio
                  v-for="option in target.radioGroupOptions"
                  :key="option.label"
                  :label="option.value"
                >
                  {{ option.label }}
                </el-radio>
              </el-radio-group>
            </template>

            <template v-else-if="target.component === 'select'">
              <el-select
                filterable
                clearable
                :value="formData[target.prop]"
                @input="handleInput(target.prop, $event)"
                filterable
                clearable
                style="width: 100%"
                :multiple="target.multiple"
                placeholder="请选择"
                @change="target.onSelect && target.onSelect($event)"
              >
                <el-option
                  v-for="option in target.selectGroupOptions || []"
                  :key="option.value"
                  :label="option.label"
                  :value="option.value"
                />
              </el-select>
            </template>

            <template v-else-if="target.component === 'date'">
              <el-date-picker
                :style="{
                  width: target && target.width ? target.width : '100%',
                }"
                :value="formData[target.prop]"
                @input="handleInput(target.prop, $event)"
                type="date"
              />
            </template>

            <template v-else-if="target.component === 'upload'">
              <el-upload
                :limit="1"
                ref="upload"
                :before-upload="target.beforeUpload"
              >
                <el-button
                  style="margin-left: 10px"
                  size="small"
                  type="primary"
                >
                  上传秘钥
                </el-button>
              </el-upload>
            </template>

            <template v-else-if="target.component === 'imgUpload'">
              <el-upload
                :limit="1"
                list-type="picture"
                :file-list="formData[target.prop]"
                ref="upload"
                :before-upload="target.beforeUpload"
                :on-change="target.onSuccess"
              >
                <el-button
                  style="margin-left: 10px"
                  size="small"
                  type="primary"
                >
                  上传图片
                </el-button>
              </el-upload>
            </template>

            <template v-else-if="target.component === 'action'">
              <div
                class="pageForm-btns"
                :style="{
                  paddingRight: width ? width : '130px',
                }"
              >
                <div
                  v-for="(action, index) in target.componentProps"
                  :key="index"
                  style="margin-left: 10px"
                >
                  <el-button
                    v-bind="action"
                    @click="() => action.click && action.click(action, index)"
                  >
                    {{ action.label }}
                  </el-button>
                </div>
              </div>
            </template>

            <template v-else-if="target.component === 'slot'">
              <slot />
            </template>

            <template v-else-if="target.component === 'enum'">
              <el-select
                :value="formData[target.prop]"
                @input="handleInput(target.prop, $event)"
                filterable
                clearable
                style="width: 100%"
              >
                <el-option
                  v-for="option in getEnum(target.enumName)"
                  :key="option.value"
                  :label="option.text"
                  :value="option.value"
                />
              </el-select>
            </template>

            <template v-else-if="target.component === 'bool'">
              <el-select
                :value="formData[target.prop]"
                @input="handleInput(target.prop, $event)"
                filterable
                clearable
                style="width: 100%"
              >
                <el-option label="是" value="1" />
                <el-option label="否" value="0" />
              </el-select>
            </template>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>

<script>
export default {
  name: "PageForm",
  model: {
    prop: "formData",
    event: "input",
  },
  props: {
    list: {
      type: Array,
      required: true,
      default: () => [],
    },
    rules: {
      type: Object,
      default: () => ({}),
    },
    width: {
      type: String,
      default: "130px",
    },
    formData: {
      type: Object,
      default: () => ({}),
    },
    labelPosition: {
      type: String,
      default: "left",
    },
    labelWidth: {
      type: String,
      default: "100px",
    },
  },
  computed: {
    // 暴露表单引用给父组件
    ruleFormRef() {
      return this.$refs.ruleFormRef;
    },
  },
  methods: {
    getEnum(enumName) {
      const enums = this.$store.state.enums;
      const enumList = enums[enumName];
      return enumList || [];
    },
    // 处理表单数据的双向绑定
    handleInput(prop, value) {
      // 创建新的 formData 对象以触发响应式更新
      const newFormData = { ...this.formData };
      newFormData[prop] = value;
      // 同时发出两个事件以兼容 v-model 和 .sync
      this.$emit("input", newFormData);
      this.$emit("update:formData", newFormData);
    },

    // 暴露表单验证方法
    validate(callback) {
      return this.$refs.ruleFormRef.validate(callback);
    },

    // 暴露表单重置方法
    resetFields() {
      this.$refs.ruleFormRef.resetFields();
    },

    // 暴露清空验证方法
    clearValidate(props) {
      this.$refs.ruleFormRef.clearValidate(props);
    },
  },
};
</script>

<style scoped lang="scss">
.PageForm {
  width: 100%;
  height: 100%;

  .pageForm-btns {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 15px;
    width: 100%;
  }
}
</style>
